/*
 * Copyright (c) 1994, 2021, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

package java.lang;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;
import java.io.Serializable;
import java.io.StreamCorruptedException;
import java.util.Arrays;

/**
 * 线程安全的可变字符序列。
 * 字符串缓冲区类似于 {@link String}，但可以修改。在任何时间点，它都包含某个特定的字符序列，
 * 但可以通过某些方法调用来更改序列的长度和内容。
 * <p>
 * 字符串缓冲区可安全地用于多个线程。这些方法在必要的地方进行了同步，
 * 以便任何特定实例上的所有操作就好像是按照与每个涉及的单个线程所进行的方法调用的顺序
 * 一致的某个串行顺序来发生的。
 * <p>
 * {@code StringBuffer} 上的主要操作是 {@code append} 和 {@code insert} 方法，
 * 可重载这些方法，以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串，
 * 然后将该字符串的字符追加或插入到字符串缓冲区中。{@code append} 方法始终将这些字符
 * 添加到缓冲区的末端；{@code insert} 方法则在指定的点添加字符。
 * <p>
 * 例如，如果 {@code z} 引用一个当前内容是 {@code "start"} 的字符串缓冲区对象，
 * 则此方法调用 {@code z.append("le")} 会使字符串缓冲区包含 {@code "startle"}，
 * 而 {@code z.insert(4, "le")} 将更改字符串缓冲区，使其包含 {@code "starlet"}。
 * <p>
 * 通常，如果 sb 引用 {@code StringBuffer} 的一个实例，则 {@code sb.append(x)}
 * 和 {@code sb.insert(sb.length(), x)} 具有相同的效果。
 * <p>
 * 每当发生涉及源序列的操作（如从源序列追加或插入）时，此类只在执行操作的字符串缓冲区上
 * 同步，而不在源上同步。请注意，虽然 {@code StringBuffer} 设计为可以安全地从多个线程
 * 并发使用，但如果构造方法或 {@code append} 或 {@code insert} 操作传递一个在线程间
 * 共享的源序列，则调用代码必须确保该操作在操作期间对源序列具有一致且不变的视图。
 * 这可以通过调用者在操作调用期间保持锁定、使用不可变的源序列或不在线程间共享源序列来满足。
 * <p>
 * 每个字符串缓冲区都有一定的容量。只要字符串缓冲区所包含的字符序列的长度没有超出此容量，
 * 就无需分配新的内部缓冲区数组。如果内部缓冲区溢出，则此容量自动增大。
 * <p>
 * 除非另有说明，否则将 {@code null} 参数传递给此类中的构造方法或方法将导致抛出
 * {@link NullPointerException}。
 * <p>
 * 从 JDK 5 发行版开始，为该类补充了一个单个线程使用的等价类，即 {@link StringBuilder}。
 * 与此类相比，通常应该优先使用 {@code StringBuilder} 类，因为它支持所有相同的操作，
 * 但由于它不执行同步，所以速度更快。
 *
 * @author      Arthur van Hoff
 * @see     java.lang.StringBuilder
 * @see     java.lang.String
 * @since   JDK1.0
 */
 public final class StringBuffer
    extends AbstractStringBuilder
    implements Serializable, CharSequence
{

    /**
     * toString 返回的最后一个值的缓存。每当 StringBuffer 被修改时清除。
     */
    private transient char[] toStringCache;

    /** use serialVersionUID from JDK 1.0.2 for interoperability */
    static final long serialVersionUID = 3388685877147921107L;

    /**
     * 构造一个其中不带字符的字符串缓冲区，其初始容量为 16 个字符。
     */
    public StringBuffer() {
        super(16);
    }

    /**
     * 构造一个其中不带字符的字符串缓冲区，其初始容量由 {@code capacity} 参数指定。
     *
     * @param      capacity  初始容量。
     * @exception  NegativeArraySizeException  如果 {@code capacity} 参数小于 {@code 0}。
     */
    public StringBuffer(int capacity) {
        super(capacity);
    }

    /**
     * 构造一个字符串缓冲区，并将其初始化为指定字符串的内容。
     * 该字符串缓冲区的初始容量为 {@code 16} 加上字符串参数的长度。
     *
     * @param   str   缓冲区的初始内容。
     */
    public StringBuffer(String str) {
        super(str.length() + 16);
        append(str);
    }

    /**
     * 构造一个字符串缓冲区，它包含与指定的 {@code CharSequence} 相同的字符。
     * 该字符串缓冲区的初始容量为 {@code 16} 加上 {@code CharSequence} 参数的长度。
     * <p>
     * 如果指定的 {@code CharSequence} 的长度小于或等于零，则返回容量为 {@code 16}
     * 的空缓冲区。
     *
     * @param      seq   要复制的序列。
     * @since 1.5
     */
    public StringBuffer(CharSequence seq) {
        this(seq.length() + 16);
        append(seq);
    }

    @Override
    public synchronized int length() {
        return count;
    }

    @Override
    public synchronized int capacity() {
        return value.length;
    }


    @Override
    public synchronized void ensureCapacity(int minimumCapacity) {
        super.ensureCapacity(minimumCapacity);
    }

    /**
     * @since      1.5
     */
    @Override
    public synchronized void trimToSize() {
        super.trimToSize();
    }

    /**
     * @throws IndexOutOfBoundsException {@inheritDoc}
     * @see        #length()
     */
    @Override
    public synchronized void setLength(int newLength) {
        toStringCache = null;
        super.setLength(newLength);
    }

    /**
     * @throws IndexOutOfBoundsException {@inheritDoc}
     * @see        #length()
     */
    @Override
    public synchronized char charAt(int index) {
        if ((index < 0) || (index >= count))
            throw new StringIndexOutOfBoundsException(index);
        return value[index];
    }

    /**
     * @since      1.5
     */
    @Override
    public synchronized int codePointAt(int index) {
        return super.codePointAt(index);
    }

    /**
     * @since     1.5
     */
    @Override
    public synchronized int codePointBefore(int index) {
        return super.codePointBefore(index);
    }

    /**
     * @since     1.5
     */
    @Override
    public synchronized int codePointCount(int beginIndex, int endIndex) {
        return super.codePointCount(beginIndex, endIndex);
    }

    /**
     * @since     1.5
     */
    @Override
    public synchronized int offsetByCodePoints(int index, int codePointOffset) {
        return super.offsetByCodePoints(index, codePointOffset);
    }

    /**
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    @Override
    public synchronized void getChars(int srcBegin, int srcEnd, char[] dst,
                                      int dstBegin)
    {
        super.getChars(srcBegin, srcEnd, dst, dstBegin);
    }

    /**
     * @throws IndexOutOfBoundsException {@inheritDoc}
     * @see        #length()
     */
    @Override
    public synchronized void setCharAt(int index, char ch) {
        if ((index < 0) || (index >= count))
            throw new StringIndexOutOfBoundsException(index);
        toStringCache = null;
        value[index] = ch;
    }

    @Override
    public synchronized StringBuffer append(Object obj) {
        toStringCache = null;
        super.append(String.valueOf(obj));
        return this;
    }

    @Override
    public synchronized StringBuffer append(String str) {
        toStringCache = null;
        super.append(str);
        return this;
    }

    /**
     * 将指定的 {@code StringBuffer} 追加到此序列。
     * <p>
     * {@code StringBuffer} 参数的字符按顺序追加到此 {@code StringBuffer} 的内容中，
     * 使此 {@code StringBuffer} 的长度增加参数的长度。
     * 如果 {@code sb} 为 {@code null}，则将四个字符 {@code "null"} 追加到此 {@code StringBuffer}。
     * <p>
     * 设 <i>n</i> 为旧字符序列的长度，即在执行 {@code append} 方法之前
     * {@code StringBuffer} 中包含的字符序列。那么新字符序列中索引 <i>k</i> 处的字符
     * 等于旧字符序列中索引 <i>k</i> 处的字符（如果 <i>k</i> 小于 <i>n</i>）；
     * 否则，它等于参数 {@code sb} 中索引 <i>k-n</i> 处的字符。
     * <p>
     * 此方法在 {@code this}（目标对象）上同步，但不在源（{@code sb}）上同步。
     *
     * @param   sb   要追加的 {@code StringBuffer}。
     * @return  对此对象的引用。
     * @since 1.4
     */
    public synchronized StringBuffer append(StringBuffer sb) {
        toStringCache = null;
        super.append(sb);
        return this;
    }

    /**
     * @since 1.8
     */
    @Override
    synchronized StringBuffer append(AbstractStringBuilder asb) {
        toStringCache = null;
        super.append(asb);
        return this;
    }

    /**
     * 将指定的 {@code CharSequence} 追加到此序列。
     * <p>
     * {@code CharSequence} 参数的字符按顺序追加，
     * 使此序列的长度增加参数的长度。
     *
     * <p>此方法的结果与调用 this.append(s, 0, s.length()) 完全相同；
     *
     * <p>此方法在 {@code this}（目标对象）上同步，但不在源（{@code s}）上同步。
     *
     * <p>如果 {@code s} 为 {@code null}，则追加四个字符 {@code "null"}。
     *
     * @param   s 要追加的 {@code CharSequence}。
     * @return  对此对象的引用。
     * @since 1.5
     */
    @Override
    public synchronized StringBuffer append(CharSequence s) {
        toStringCache = null;
        super.append(s);
        return this;
    }

    /**
     * @throws IndexOutOfBoundsException {@inheritDoc}
     * @since      1.5
     */
    @Override
    public synchronized StringBuffer append(CharSequence s, int start, int end)
    {
        toStringCache = null;
        super.append(s, start, end);
        return this;
    }

    @Override
    public synchronized StringBuffer append(char[] str) {
        toStringCache = null;
        super.append(str);
        return this;
    }

    /**
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    @Override
    public synchronized StringBuffer append(char[] str, int offset, int len) {
        toStringCache = null;
        super.append(str, offset, len);
        return this;
    }

    @Override
    public synchronized StringBuffer append(boolean b) {
        toStringCache = null;
        super.append(b);
        return this;
    }

    @Override
    public synchronized StringBuffer append(char c) {
        toStringCache = null;
        super.append(c);
        return this;
    }

    @Override
    public synchronized StringBuffer append(int i) {
        toStringCache = null;
        super.append(i);
        return this;
    }

    /**
     * @since 1.5
     */
    @Override
    public synchronized StringBuffer appendCodePoint(int codePoint) {
        toStringCache = null;
        super.appendCodePoint(codePoint);
        return this;
    }

    @Override
    public synchronized StringBuffer append(long lng) {
        toStringCache = null;
        super.append(lng);
        return this;
    }

    @Override
    public synchronized StringBuffer append(float f) {
        toStringCache = null;
        super.append(f);
        return this;
    }

    @Override
    public synchronized StringBuffer append(double d) {
        toStringCache = null;
        super.append(d);
        return this;
    }

    /**
     * @throws StringIndexOutOfBoundsException {@inheritDoc}
     * @since      1.2
     */
    @Override
    public synchronized StringBuffer delete(int start, int end) {
        toStringCache = null;
        super.delete(start, end);
        return this;
    }

    /**
     * @throws StringIndexOutOfBoundsException {@inheritDoc}
     * @since      1.2
     */
    @Override
    public synchronized StringBuffer deleteCharAt(int index) {
        toStringCache = null;
        super.deleteCharAt(index);
        return this;
    }

    /**
     * @throws StringIndexOutOfBoundsException {@inheritDoc}
     * @since      1.2
     */
    @Override
    public synchronized StringBuffer replace(int start, int end, String str) {
        toStringCache = null;
        super.replace(start, end, str);
        return this;
    }

    /**
     * @throws StringIndexOutOfBoundsException {@inheritDoc}
     * @since      1.2
     */
    @Override
    public synchronized String substring(int start) {
        return substring(start, count);
    }

    /**
     * @throws IndexOutOfBoundsException {@inheritDoc}
     * @since      1.4
     */
    @Override
    public synchronized CharSequence subSequence(int start, int end) {
        return super.substring(start, end);
    }

    /**
     * @throws StringIndexOutOfBoundsException {@inheritDoc}
     * @since      1.2
     */
    @Override
    public synchronized String substring(int start, int end) {
        return super.substring(start, end);
    }

    /**
     * @throws StringIndexOutOfBoundsException {@inheritDoc}
     * @since      1.2
     */
    @Override
    public synchronized StringBuffer insert(int index, char[] str, int offset,
                                            int len)
    {
        toStringCache = null;
        super.insert(index, str, offset, len);
        return this;
    }

    /**
     * @throws StringIndexOutOfBoundsException {@inheritDoc}
     */
    @Override
    public synchronized StringBuffer insert(int offset, Object obj) {
        toStringCache = null;
        super.insert(offset, String.valueOf(obj));
        return this;
    }

    /**
     * @throws StringIndexOutOfBoundsException {@inheritDoc}
     */
    @Override
    public synchronized StringBuffer insert(int offset, String str) {
        toStringCache = null;
        super.insert(offset, str);
        return this;
    }

    /**
     * @throws StringIndexOutOfBoundsException {@inheritDoc}
     */
    @Override
    public synchronized StringBuffer insert(int offset, char[] str) {
        toStringCache = null;
        super.insert(offset, str);
        return this;
    }

    /**
     * @throws IndexOutOfBoundsException {@inheritDoc}
     * @since      1.5
     */
    @Override
    public StringBuffer insert(int dstOffset, CharSequence s) {
        // 注意，通过调用其他 StringBuffer 方法实现同步
        // 在将 s 缩小到特定类型之后
        // toStringCache 清理同样如此
        super.insert(dstOffset, s);
        return this;
    }

    /**
     * @throws IndexOutOfBoundsException {@inheritDoc}
     * @since      1.5
     */
    @Override
    public synchronized StringBuffer insert(int dstOffset, CharSequence s,
            int start, int end)
    {
        toStringCache = null;
        super.insert(dstOffset, s, start, end);
        return this;
    }

    /**
     * @throws StringIndexOutOfBoundsException {@inheritDoc}
     */
    @Override
    public  StringBuffer insert(int offset, boolean b) {
        // 注意，通过调用 StringBuffer insert(int, String) 实现同步
        // 在超类方法将 b 转换为 String 之后
        // toStringCache 清理同样如此
        super.insert(offset, b);
        return this;
    }

    /**
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    @Override
    public synchronized StringBuffer insert(int offset, char c) {
        toStringCache = null;
        super.insert(offset, c);
        return this;
    }

    /**
     * @throws StringIndexOutOfBoundsException {@inheritDoc}
     */
    @Override
    public StringBuffer insert(int offset, int i) {
        // 注意，通过调用 StringBuffer insert(int, String) 实现同步
        // 在超类方法将 i 转换为 String 之后
        // toStringCache 清理同样如此
        super.insert(offset, i);
        return this;
    }

    /**
     * @throws StringIndexOutOfBoundsException {@inheritDoc}
     */
    @Override
    public StringBuffer insert(int offset, long l) {
        // 注意，通过调用 StringBuffer insert(int, String) 实现同步
        // 在超类方法将 l 转换为 String 之后
        // toStringCache 清理同样如此
        super.insert(offset, l);
        return this;
    }

    /**
     * @throws StringIndexOutOfBoundsException {@inheritDoc}
     */
    @Override
    public StringBuffer insert(int offset, float f) {
        // 注意，通过调用 StringBuffer insert(int, String) 实现同步
        // 在超类方法将 f 转换为 String 之后
        // toStringCache 清理同样如此
        super.insert(offset, f);
        return this;
    }

    /**
     * @throws StringIndexOutOfBoundsException {@inheritDoc}
     */
    @Override
    public StringBuffer insert(int offset, double d) {
        // 注意，通过调用 StringBuffer insert(int, String) 实现同步
        // 在超类方法将 d 转换为 String 之后
        // toStringCache 清理同样如此
        super.insert(offset, d);
        return this;
    }

    /**
     * @since      1.4
     */
    @Override
    public int indexOf(String str) {
        // 注意，通过调用其他 StringBuffer 方法实现同步
        return super.indexOf(str);
    }

    /**
     * @since      1.4
     */
    @Override
    public synchronized int indexOf(String str, int fromIndex) {
        return super.indexOf(str, fromIndex);
    }

    /**
     * @since      1.4
     */
    @Override
    public int lastIndexOf(String str) {
        // 注意，通过调用其他 StringBuffer 方法实现同步
        return lastIndexOf(str, count);
    }

    /**
     * @since      1.4
     */
    @Override
    public synchronized int lastIndexOf(String str, int fromIndex) {
        return super.lastIndexOf(str, fromIndex);
    }

    /**
     * @since   JDK1.0.2
     */
    @Override
    public synchronized StringBuffer reverse() {
        toStringCache = null;
        super.reverse();
        return this;
    }

    @Override
    public synchronized String toString() {
        if (toStringCache == null) {
            toStringCache = Arrays.copyOfRange(value, 0, count);
        }
        return new String(toStringCache, true);
    }

    /**
     * StringBuffer 的可序列化字段。
     *
     * @serialField value  char[]
     *              此 StringBuffer 的底层字符数组。
     * @serialField count int
     *              此 StringBuffer 中的字符数。
     * @serialField shared  boolean
     *              指示底层数组是否共享的标志。
     *              反序列化时忽略此值。
     */
    private static final ObjectStreamField[] serialPersistentFields =
    {
        new ObjectStreamField("value", char[].class),
        new ObjectStreamField("count", Integer.TYPE),
        new ObjectStreamField("shared", Boolean.TYPE),
    };

    /**
     * 调用 {@code writeObject} 方法将 {@code StringBuffer} 的状态写入流。
     */
    private synchronized void writeObject(ObjectOutputStream s)
        throws IOException {
        ObjectOutputStream.PutField fields = s.putFields();
        fields.put("value", value);
        fields.put("count", count);
        fields.put("shared", false);
        s.writeFields();
    }

    /**
     * 调用 {@code readObject} 方法从流中恢复 {@code StringBuffer} 的状态。
     */
    private void readObject(ObjectInputStream s)
        throws IOException, ClassNotFoundException {
        ObjectInputStream.GetField fields = s.readFields();
        char[] val = (char[])fields.get("value", null);
        int c = fields.get("count", 0);
        if (c < 0 || c > val.length) {
            throw new StreamCorruptedException("count value invalid");
        }
        count = c;
        value = val;
    }
}
